home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / dnsconf / dns.c < prev    next >
C/C++ Source or Header  |  1996-06-30  |  10KB  |  389 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/stat.h>
  5. #include "../misc/misc.h"
  6. #include "dnsconf.h"
  7. #include "internal.h"
  8. #include "../paths.h"
  9.  
  10. extern DNSCONF_HELP_FILE help_dnsconf;
  11.  
  12. CONFIG_FILE f_boot (ETC_NAMED_BOOT,help_dnsconf
  13.     ,CONFIGF_MANAGED|CONFIGF_OPTIONNAL|CONFIGF_PROBED);
  14.  
  15. static int dns_is_reverse(const char *str)
  16. {
  17.     int ret = 0;
  18.     char buf[200];
  19.     strcpy (buf,str);
  20.     strupr (buf);
  21.     char *pt = strstr(buf,".IN-ADDR.ARPA");
  22.     if (pt != NULL){
  23.         if (pt[13] == '\0'){
  24.             ret = 1;
  25.         }
  26.     }
  27.     return ret;
  28. }
  29.  
  30.  
  31. PRIVATE void DNS::parse(const char *buf, const char *fpath, int noline)
  32. {
  33.     char words[10][500];
  34.     for (int i=0; i<10; i++) words[i][0] = '\0';
  35.     int nb = sscanf (buf,"%s %s %s %s %s %s %s %s %s %s"
  36.         ,words[0],words[1],words[2],words[3]
  37.         ,words[4],words[5],words[6],words[7]
  38.         ,words[8],words[9]);
  39.     if (strcmp(words[0],"directory")==0){
  40.         pathcfg.setfrom (words[1]);
  41.     }else if (strcmp(words[0],"cache")==0){
  42.         cachefiles.add (new CACHEFILE (words[1],words[2]));
  43.     }else if (strcmp(words[0],"primary")==0){
  44.         if (dns_is_reverse(words[1])){
  45.             primarys_rev.add (new PRIMARY_REV(words[1]
  46.                 ,words[2],pathcfg.get()));
  47.         }else{
  48.             primarys.add (new PRIMARY(words[1],words[2]
  49.                 ,pathcfg.get()));
  50.         }
  51.     }else if (strcmp(words[0],"secondary")==0){
  52.         const char *tbip[8];
  53.         for (int i=0; i<8; i++) tbip[i] = words[i+2];
  54.         secondarys.add (new SECONDARY (words[1],words[nb-1]
  55.             ,tbip,nb-3));
  56.     }else if (strcmp(words[0],"forwarders")==0){
  57.         nbforward = nb - 1;
  58.         for (int f=1; f<nb; f++) forwarders[f-1].setfrom(words[f]);
  59.     }else if (strcmp(words[0],"slave")==0){
  60.         slave = 1;
  61.     }else{
  62.         xconf_error ("Invalid keyword %s, file %s line %d\n"
  63.             ,words[0],fpath,noline);
  64.     }
  65. }
  66.  
  67.  
  68. /*
  69.     Add the reverse mapping for the loopback network
  70. */
  71. PUBLIC void DNS::setlocalhost()
  72. {
  73.     PRIMARY_REV *pri = new PRIMARY_REV;
  74.     pri->domainv.setfrom ("127.0.0");
  75.     pri->setfromv();
  76.     pri->file.setfrom ("127.0.0");
  77.     pri->addrec (new RECORD_IN_SOA);
  78.     pri->addrec (new RECORD_IN_NS);
  79.     pri->addrec (new RECORD_IN_PTR ("1","localhost."));
  80.     primarys_rev.add (pri);
  81. }
  82.  
  83. PUBLIC DNS::DNS()
  84. {
  85.     slave = 0;
  86.     pathcfg.setfrom ("/var/named");
  87.     nbforward = 0;
  88.     FILE *fin = f_boot.fopen ("r");
  89.     if (fin != NULL){
  90.         char buf[500];
  91.         int noline = 0;
  92.         while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
  93.             noline++;
  94.             strip_end (buf);
  95.             char *pt = str_skip(buf);
  96.             /* #Specification: dnsconf / /etc/named.boot / comments
  97.                 Comments in /etc/named.boot are not preserve
  98.                 by dnsconf
  99.             */
  100.             if (*pt != '\0' && *pt != ';'){
  101.                 parse (buf,f_boot.getpath(),noline);
  102.             }
  103.         }
  104.     }
  105. }
  106.  
  107. /*
  108.     Return != 0 if the DNS is not configured at all
  109. */
  110. PUBLIC int DNS::empty()
  111. {
  112.     return primarys.getnb()==0 && primarys_rev.getnb()==0;
  113. }
  114.  
  115. PUBLIC void DNS::basiccheck()
  116. {
  117.     if (cachefiles.getnb()==0){
  118.         cachefiles.add (new CACHEFILE(".","root.cache"));
  119.     }
  120.     FQHOST rfq ("1.0.0.127.in-addr.arpa");
  121.     PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
  122.     if (rev == NULL){
  123.         /* #Specification; dnsconf / check / local domain
  124.             Dnsconf make sure the domain
  125.             0.0.127.in-addr.arpa is defined. If not it is
  126.             added with a single PTR entry.
  127.             #
  128.             1    IN    PTR    localhost.
  129.             #
  130.         */
  131.         setlocalhost();
  132.     }
  133. }
  134.     
  135. /*
  136.     Write all configuration files of the DNS.
  137.     Return -1 if any error.
  138. */
  139. PUBLIC int DNS::write ()
  140. {
  141.     int ret = -1;
  142.     /* #Specification: dnsconf / writing /etc/named.boot
  143.         The file /etc/named.boot is rewritten everytime any
  144.         of the DNS files are rewritten. This give a hint
  145.         to netconf to instruct named to restart(reload) just
  146.         by looking at the revision date of /etc/named.boot.
  147.     */
  148.     FILE *fout = f_boot.fopen ("w");
  149.     if (fout != NULL){
  150.         const char *cfg = pathcfg.get();
  151.         struct stat st;
  152.         if (stat(cfg,&st)==-1) mkdir (cfg,0755);
  153.         fprintf (fout,"directory\t%s\n",cfg);
  154.         for (int i=0; i<cachefiles.getnb(); i++){
  155.             CACHEFILE *c = cachefiles.getitem(i);
  156.             fprintf (fout,"cache\t%s\t%s\n",c->domain.get()
  157.                 ,c->path.get());
  158.         }
  159.         const char *named_dir = pathcfg.get();
  160.         ret = primarys.write(fout,named_dir);
  161.         ret = primarys_rev.write(fout,named_dir);
  162.         secondarys.write(fout,named_dir);
  163.         if (nbforward > 0){
  164.             fputs ("forwarders",fout);
  165.             for (int f=0; f<MAX_FORWARDERS; f++){
  166.                 fputc (' ',fout);
  167.                 fputs (forwarders[f].get(),fout);
  168.             }
  169.             fputc ('\n',fout);
  170.         }
  171.         if (slave) fprintf (fout,"slave\n");
  172.         fclose (fout);
  173.     }
  174.     return ret;
  175. }
  176. #if 0
  177. static void qualify(
  178.     const char *fqhost,
  179.     char *host,
  180.     char *domain)
  181. {
  182.     char *pt = strchr(fqhost,'.');
  183.     if (pt != NULL){
  184.         strcpy (domain,pt+1);
  185.         int len = (int)(pt-fqhost);
  186.         memcpy (host,fqhost,len);
  187.         host[len] = '\0';
  188.     }else{
  189.         strcpy (host,fqhost);
  190.         RESOLV res;
  191.         strcpy (domain,res.domain.get());
  192.     }
  193. }
  194. #endif
  195.  
  196. /*
  197.     Add or replace record  (A and PTRs) for a host
  198. */
  199. PUBLIC int DNS::set (
  200.     const char *fqhost,    // Fully qualified name, or name
  201.                 // relative to our own domain
  202.     const char *tbip[],    // May set several IP number for
  203.     int nbip)        // one host at once
  204. {
  205.     /* #Specification: dnsconf / set a host / multiple IP
  206.         A host may have several IP number in the DNS. The
  207.         first one is known as the official one. So a
  208.         host may have several A record and several
  209.         corresponding PTR records.
  210.     */
  211.     FQHOST fq (fqhost);
  212.     /* #Specification: dnsconf / setting new spec for a host
  213.         dnsconf use a fairly simple way to update a host
  214.         definition. It simply delete everything relate
  215.         to that host (A record and PTR record) and add
  216.         records in the proper primarys.
  217.  
  218.         There is no chance, using this strategy, to keep the
  219.         original ordering of the record files. This is
  220.         why dnsconf always sort those before writing.
  221.     */
  222.     unset (fqhost);
  223.     // Checking if this DNS is the primary for the domain
  224.     PRIMARY *pri = primarys.getitem(fq,NULL);
  225.     if (pri != NULL){
  226.         for (int i=0; i<nbip; i++){
  227.             pri->set (fq
  228.                 ,new RECORD_IN_A("dummy",tbip[i]));
  229.         }
  230.     }
  231.     PRIMARY *onerev = NULL;
  232.     for (int noip=0; noip < nbip; noip++){
  233.         const char *ip = tbip[noip];
  234.         IP_ADDR ipa;
  235.         ipa.setfrom(ip);
  236.         char revdom[40];
  237.         ipa.setrev(revdom);
  238.         FQHOST rfq (revdom);
  239.         PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
  240.         if (rev != NULL){
  241.             char fqdn[PATH_MAX];
  242.             fq.formatfull (fqdn);
  243.             rev->set (rfq
  244.                 ,new RECORD_IN_PTR("dummy",fqdn));
  245.             onerev = rev;
  246.         }
  247.     }
  248.     int ret = -1;
  249.     if (pri != NULL || onerev != NULL) ret = 0;
  250.     return ret;
  251. }
  252. /*
  253.     Add or replace NS record for a host
  254.     Return -1 if the information could not be added to any domain.
  255. */
  256. PUBLIC int DNS::setns (
  257.     const SSTRING &fqhost,    // Fully qualified name, or name
  258.                 // relative to our own domain
  259.     const SSTRINGS &tbns)    // May set several NS for
  260.                 // one host at once
  261. {
  262.     /* #Specification: dnsconf / set a domain / multiple NS
  263.         A domain may have several NS record in the DNS. The
  264.         first one is known as the official one. The others
  265.         are secondaries.
  266.     */
  267.     FQHOST fq (fqhost);
  268.     unsetns (fqhost);
  269.     int ret = -1;
  270.     for (int i=0; i<2; i++){
  271.         /* #Specification: dnsconf / domain and sub-domain
  272.             A DNS may hold information for a domain and
  273.             for sub-domain. When updating the NS records
  274.             of a sub-domain, we also update NS records
  275.             in the parent domain automaticly.
  276.         */
  277.         PRIMARY *pri = primarys.getitem(fq,NULL,i);
  278.         if (pri != NULL){
  279.             int nbns = tbns.getnb();
  280.             for (int i=0; i<nbns; i++){
  281.                 SSTRING *ns = tbns.getitem(i);
  282.                 if (!ns->is_empty()){
  283.                     pri->set (fq
  284.                         ,new RECORD_IN_NS("dummy"
  285.                         ,ns->get()));
  286.                 }
  287.             }
  288.             ret = 0;
  289.         }
  290.     }
  291.     return ret;
  292. }
  293. /*
  294.     Add or replace MX record for a host
  295. */
  296. PUBLIC int DNS::setmx (
  297.     const SSTRING &fqhost,    // Fully qualified name, or name
  298.                 // relative to our own domain
  299.     const SSTRINGS &tbmx)    // May set several MX for
  300.                 // one host at once
  301. {
  302.     /* #Specification: dnsconf / set a host / multiple MX
  303.         A host may have several MX record in the DNS. dnsconf
  304.         automaticly assign a priority number based on the
  305.         order the different MXs are given.
  306.     */
  307.     FQHOST fq (fqhost);
  308.     unsetmx (fqhost);
  309.     PRIMARY *pri = primarys.getitem(fq,NULL);
  310.     if (pri != NULL){
  311.         int nbmx = tbmx.getnb();
  312.         for (int i=0; i<nbmx; i++){
  313.             SSTRING *mx = tbmx.getitem(i);
  314.             if (!mx->is_empty()){
  315.                 pri->set (fq
  316.                     ,new RECORD_IN_MX("dummy"
  317.                     ,i*5+5,mx->get()));
  318.             }
  319.         }
  320.     }
  321.     return (pri != NULL) ? 0 : -1;
  322. }
  323.  
  324. /*
  325.     Remove all reference to a host in the DNS
  326. */
  327. PUBLIC void DNS::unset (const char *fqhost)
  328. {
  329.     FQHOST fq (fqhost);
  330.     char hostpart[200];
  331.     PRIMARY *pri = primarys.getitem(fq,hostpart);
  332.     if (pri != NULL){
  333.         pri->unset (new RECORD_IN_A(hostpart,"1.1.1.1"));
  334.     }
  335.     char full[200];
  336.     fq.formatfull (full);
  337.     for (int i=0; i<primarys_rev.getnb(); i++){
  338.         PRIMARY *pri = primarys_rev.getitem(i);
  339.         pri->unset (new RECORD_IN_PTR("1",full));
  340.     }
  341. }
  342.  
  343.  
  344. /*
  345.     Remove all reference to a host in the DNS
  346. */
  347. PUBLIC void DNS::unsetns (const SSTRING &fqhost)
  348. {
  349.     FQHOST fq (fqhost);
  350.     char hostpart[200];
  351.     for (int i=0; i<2; i++){
  352.         PRIMARY *pri = primarys.getitem(fq,hostpart,i);
  353.         if (pri != NULL){
  354.             pri->unset (new RECORD_IN_NS(hostpart,"dummy"));
  355.         }
  356.     }
  357. }
  358. /*
  359.     Remove all reference to a host in the DNS
  360. */
  361. PUBLIC void DNS::unsetmx (const SSTRING &fqhost)
  362. {
  363.     FQHOST fq (fqhost);
  364.     char hostpart[200];
  365.     PRIMARY *pri = primarys.getitem(fq,hostpart);
  366.     if (pri != NULL){
  367.         pri->unset (new RECORD_IN_MX(hostpart,0,"dummy"));
  368.     }
  369. }
  370.  
  371. /*
  372.     Set a cname record (replace/add/remove)
  373. */
  374. PUBLIC void DNS::setcname (const SSTRING &fqhost, const SSTRING &cname)
  375. {
  376.     FQHOST fq (fqhost);
  377.     char hostpart[200];
  378.     PRIMARY *pri = primarys.getitem(fq,hostpart);
  379.     if (pri != NULL){
  380.         pri->unset (new RECORD_IN_CNAME(hostpart,"dummy"));
  381.         if (!cname.is_empty()){
  382.             pri->set (fq,new RECORD_IN_CNAME(hostpart
  383.                 ,cname.get()));
  384.         }
  385.     }
  386. }
  387.  
  388.  
  389.